/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "MyTest"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <thread>
#include<sys/types.h>
#include<sys/stat.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>

#include <gui/BufferQueue.h>
#include <gui/BufferQueueDefs.h>
#include <gui/ConsumerBase.h>
#include <ui/FenceTime.h>
#include <ui/GraphicBuffer.h>

#include "platform_gralloc4.h" //librga

#include "FakeCameraConsumer.h"

#include "FakeCameraConsumer.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <fcntl.h>

using namespace android;

// Macros for including the GLConsumer name in log messages
#define LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
#define LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
#define LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
#define LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)

//////////////////////////////////////////////////////////

///graphicbuffer ///
#if 0
int gb_data[1024];

status_t gb_write(GraphicBuffer &val, void *buf, int &data_len)
{
    status_t err;

    // size if needed
    const size_t len = val.getFlattenedSize();
    const size_t fd_count = val.getFdCount();

    if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
        // don't accept size_t values which may have come from an
        // inadvertent conversion from a negative int.
        return BAD_VALUE;
    }

    // err = this->writeInt32(len);
    // if (err) return err;

    // err = this->writeInt32(fd_count);
    // if (err) return err;

    // payload
    // void* const buf = this->writeInplace(len);
    // if (buf == nullptr)
    //     return BAD_VALUE;

    int* fds = nullptr;
    if (fd_count) {
        fds = new (std::nothrow) int[fd_count];
        if (fds == nullptr) {
            ALOGE("write: failed to allocate requested %zu fds", fd_count);
            return BAD_VALUE;
        }
    }

    err = val.flatten(buf, len, fds, fd_count);
    for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
        //err = this->writeDupFileDescriptor( fds[i] );

        int dupFd = fcntl(fds[i], F_DUPFD_CLOEXEC, 0);
        if (dupFd < 0) {
            printf("##########error\n");
            return -errno;
        }

        printf("fds[i]=%d, dupFd=%d\n", fds[i], dupFd);
        
        fds[i] = dupFd;
    }

    len = val.getFlattenedSize();
    fd_count = val.getFdCount();

    

    if (fd_count) {
        delete [] fds;
    }

    return err;
}

#endif

////////////////////////


#if 1

int ipc_sock;
#include "common.h"

#endif

#if 1

sp<FakeCameraConsumer> fakeCameraConsumer;

struct graphic_buffer_info_t
{
    int fd;
    int w,h,format;
    
};

static void consumer_process_thread()
{
    #define AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 0x23
    int format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
    int width = 1920;
    int height = 1080;

    uint32_t frame_size = width * height * 1.5;

    FILE *fp = fopen("/data/local/tmp/1080p_nv12_consumer.yuv", "w+");
    if (fp == NULL)
    {
        printf("fopen for write failed!\n");
    }

    printf("%s line %d\n", __FUNCTION__, __LINE__);

    const char fifo_render_name[32] = "/data/fifo_render";
    const char fifo_retrieve_name[32] = "/data/fifo_retrieve";
    int fifo_wr_fd;
    int fifo_rd_fd;
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    unlink(fifo_render_name);
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    mkfifo(fifo_render_name, 0777);

    unlink(fifo_retrieve_name);
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    mkfifo(fifo_retrieve_name, 0777);

    fifo_rd_fd = open(fifo_retrieve_name, O_RDONLY|O_CREAT|O_NONBLOCK, S_IRWXG);
    printf("%s line %d fifo_rd_fd=%d\n", __FUNCTION__, __LINE__, fifo_rd_fd);

    printf("00fifo_rd_fd=%d\n", fifo_rd_fd);
    int fd_new = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    printf("00fd_new1=%d\n", fd_new);
    int fd_new11 = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    int fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
    printf("00fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

    int fdt1 = open("/data/local/tmp/test_server", O_RDONLY);
    printf("00fdt1=%d\n", fdt1);
    int fdt2 = fcntl(fdt1, F_DUPFD_CLOEXEC, 0);
    printf("00fdt2=%d\n", fdt2);

    fd_new11 = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
    printf("000fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

    printf("%s line %d\n", __FUNCTION__, __LINE__);
    //fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
    fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
   // fifo_wr_fd = open(fifo_render_name, O_WRONLY);
printf("%s line %d fifo_wr_fd=%d\n", __FUNCTION__, __LINE__, fifo_wr_fd);
    //unlink(fifo_retrieve_name);
    //printf("%s line %d\n", __FUNCTION__, __LINE__);
    //mkfifo(fifo_retrieve_name, 0777);
    //printf("%s line %d\n", __FUNCTION__, __LINE__);
   // fifo_rd_fd = open(fifo_retrieve_name, O_RDONLY|O_CREAT|O_NONBLOCK, S_IRWXG);
///printf("%s line %d fifo_rd_fd=%d\n", __FUNCTION__, __LINE__, fifo_rd_fd);

    int clifd, listenfd;
    //{
        
        struct sockaddr_un servaddr, cliaddr;
        int ret;
        socklen_t clilen;
        struct msghdr msg;
        struct iovec iov[1];
        char buf [100];
        char  *testmsg = "test msg.\n";
    
        union {  //对齐
            struct cmsghdr cm;
            char control[CMSG_SPACE(sizeof(int))];
        }  control_un;
        struct cmsghdr  * pcmsg;
        int  recvfd;
    
        listenfd  =  socket ( AF_UNIX ,  SOCK_STREAM ,  0 ) ;
        if(listenfd < 0) {
            printf ( "socket failed.\n" ) ;
           // return  -1;
        }
    
        unlink(UNIXSTR_PATH) ;
    
        bzero (&servaddr, sizeof(servaddr));
        servaddr.sun_family = AF_UNIX;
        strcpy ( servaddr.sun_path ,  UNIXSTR_PATH ) ;
    
        ret  =  bind ( listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
        if(ret < 0) {
            printf ( "bind failed. errno = %d.\n" ,  errno ) ;
            close(listenfd);
          //  return  - 1 ;
        }
    
        listen(listenfd, 5);

        char data_ptr[32];
        int data_len = sizeof(data_ptr);

LISTEN_AGAIN:
        //while(1)
         {
            clilen = sizeof( cliaddr );
            clifd = accept( listenfd, (struct sockaddr*)&cliaddr , &clilen);
            if ( clifd < 0 ) {
                printf ( "accept failed.\n" ) ;
                //continue ;
            }

            printf ( "accept ok.\n" ) ;
        }
    //}

    while (1)
    {
        BufferItem item;
        status_t status = fakeCameraConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0), 0);
        if (status == NO_ERROR)
        {
            sp<GraphicBuffer> graphicBuffer;// = fakeCameraConsumer->mSlots[item.mSlot].mGraphicBuffer;
            fakeCameraConsumer->getGraphicBuffer(item.mSlot, graphicBuffer);
            
            uint32_t* dataOut;
            //graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut));

            //error: item.mFrameNumber is uint64_t type
            //printf("slot=%d, frameNum=%d, the data out is %d, dataOut=0x%x\n", item.mSlot, item.mFrameNumber, *dataOut, dataOut);

            //printf("slot=%d, frameNum=%llu, the data out is %d, dataOut=0x%x\n", item.mSlot, item.mFrameNumber, *dataOut, dataOut);
            //printf("slot=%d, frameNum=%d, the data out is %d, dataOut=0x%x\n", item.mSlot, (int)item.mFrameNumber, *dataOut, dataOut);

            //////////////////////////////////////////////

            //fd = open( "zieckey_fifo", O_WRONLY );
            //write(fifo_wr_fd, s, sizeof(s));

            int shared_fd = 0;
            int err = gralloc4::get_share_fd((buffer_handle_t)graphicBuffer->handle, &shared_fd);
            if (err != android::OK)
            {
                printf("gralloc4::get_share_fd failed, err=%d", err);
            }
            else
            {
#if 0
                //ipc_fd_socket_send(ipc_sock, shared_fd);
                char data_ptr[8] = "1234567";
                int data_len = sizeof(data_ptr);
                int s = ipc_fd_socket_send(ipc_sock, shared_fd, data_ptr, data_len);
                if (s <= 0)
                {
                    printf("ipc_fd_socket_send failed, err=%d", s);
                }

#else

                int recvfd = -1;
                char data_ptr[100] = "1234567";
                int data_len = sizeof(data_ptr);
                ret = ipc_fd_socket_recv(clifd, &recvfd, data_ptr, data_len);
                
                int *ptr = reinterpret_cast<int *>(static_cast<void *>(data_ptr));
                printf("recv w=%d, h=%d\n", ptr[0], ptr[1]);

                int src_width = 1920;
                int src_height = 1080;
                unsigned long src_fd = shared_fd;
                unsigned long dst_fd = recvfd;
                int dst_width = ptr[0];//640;//1920;
                int dst_height = ptr[1];//480;//1080;
                int zoom_val = 100;
                bool mirror = false;
                bool isNeedCrop = true;
                bool isDstNV21 = false;
                bool is16Align = true;
                bool isYuyvFormat = false;

                //if (src_fd > 0 && dst_fd > 0)
                {
                    int ret44 = rga_nv12_scale_crop(
                        src_width, src_height,
                        src_fd, dst_fd,
                        dst_width, dst_height,
                        zoom_val, mirror, isNeedCrop,
                        isDstNV21, is16Align, isYuyvFormat);
                    if (ret44 != 0)
                    {
                        printf("rga_nv12_scale_crop failed, ret=%d\n", ret44);
                    }
                    else
                    {
                        printf("888888999rga_nv12_scale_crop ok, ret=%d\n", ret44);
                    }
                }

                ipc_fd_socket_send(clifd, recvfd, data_ptr, data_len);

#endif
                if (fifo_wr_fd <= 0)
                {
                    //fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
                    // fifo_wr_fd = open(fifo_render_name, O_WRONLY);
                    //printf("%s line %d fifo_wr_fd=%d\n", __FUNCTION__, __LINE__, fifo_wr_fd);
                }

                if (fifo_wr_fd > 0)
                {

                    // printf("shared_fd=%d\n", shared_fd);
                    // int fd_new = fcntl(shared_fd, F_DUPFD_CLOEXEC, 0);
                    // printf("fd_new1=%d\n", fd_new);
                    // int fd_new11 = fcntl(shared_fd, F_DUPFD_CLOEXEC, 0);
                    // int fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
                    // printf("fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

                    // //write(fifo_wr_fd, &shared_fd, sizeof(int));
                    // write(fifo_wr_fd, &fd_new, sizeof(int));
                    // int retri_fd = 0;
                    // usleep(80000);
                    // read(fifo_rd_fd, &retri_fd, sizeof(int));

                    // if (shared_fd != retri_fd)
                    // {
                    //     printf("error ############ shared_fd=(%d) != retri_fd(%d)\n", shared_fd, retri_fd);
                    // }

                    //test fd rga
                    #if 0
                        int src_width = 1920;
                        int src_height = 1080;
                        static unsigned long src_fd = 0;
                        static unsigned long dst_fd = 0;
                        int dst_width = 1920;
                        int dst_height = 1080;
                        int zoom_val = 100;
                        bool mirror = false;
                        bool isNeedCrop = true;
                        bool isDstNV21 = false;
                        bool is16Align = true;
                        bool isYuyvFormat = false;

                        if (src_fd == 0) src_fd = shared_fd;

                            //                         camera2::RgaCropScale::rga_nv12_scale_crop(
                            // tempFrameWidth, tempFrameHeight, gb_shared_fd, handle_fd,
                            // halBuf.width, halBuf.height, 100, false, true,
                            // (halBuf.format == PixelFormat::YCRCB_420_SP), is16Align,
                            // false);

                        if (src_fd > 0 && dst_fd > 0)
                        {
                            int ret44 = rga_nv12_scale_crop(
                                src_width, src_height,
                                src_fd, dst_fd,
                                dst_width, dst_height,
                                zoom_val, mirror, isNeedCrop,
                                isDstNV21, is16Align, isYuyvFormat);
                            if (ret44 != 0)
                            {
                                printf("rga_nv12_scale_crop failed, ret=%d\n", ret44);
                            }
                            else
                            {
                                printf("rga_nv12_scale_crop ok, ret=%d\n", ret44);
                            }
                        }

                        dst_fd = shared_fd;

                    #endif
                }
            }

            /////////////////////////////////////////////

            if (fp)
            {
                //fwrite(dataOut, 1, frame_size, fp);
                //fflush(fp);
            }

            //graphicBuffer->unlock();

            fakeCameraConsumer->releaseBuffer(item.mSlot);
        }

        if (ret <= 0)
        {
            break;
        }

        //usleep(1000000);
        //usleep(40000);
    }

    goto LISTEN_AGAIN;

printf("%s line %d  ooo\n", __FUNCTION__, __LINE__);

    if (fp)
        fclose(fp);
}

static void consumer_process_thread11()
{
    #define AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 0x23
    int format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
    int width = 1920;
    int height = 1080;

    uint32_t frame_size = width * height * 1.5;

    FILE *fp = fopen("/data/local/tmp/1080p_nv12_consumer.yuv", "w+");
    if (fp == NULL)
    {
        printf("fopen for write failed!\n");
    }

    printf("%s line %d\n", __FUNCTION__, __LINE__);

    const char fifo_render_name[32] = "/data/fifo_render";
    const char fifo_retrieve_name[32] = "/data/fifo_retrieve";
    int fifo_wr_fd;
    int fifo_rd_fd;
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    unlink(fifo_render_name);
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    mkfifo(fifo_render_name, 0777);

    unlink(fifo_retrieve_name);
    printf("%s line %d\n", __FUNCTION__, __LINE__);
    mkfifo(fifo_retrieve_name, 0777);

    fifo_rd_fd = open(fifo_retrieve_name, O_RDONLY|O_CREAT|O_NONBLOCK, S_IRWXG);
    printf("%s line %d fifo_rd_fd=%d\n", __FUNCTION__, __LINE__, fifo_rd_fd);

    printf("00fifo_rd_fd=%d\n", fifo_rd_fd);
    int fd_new = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    printf("00fd_new1=%d\n", fd_new);
    int fd_new11 = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    int fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
    printf("00fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

    int fdt1 = open("/data/local/tmp/test_server", O_RDONLY);
    printf("00fdt1=%d\n", fdt1);
    int fdt2 = fcntl(fdt1, F_DUPFD_CLOEXEC, 0);
    printf("00fdt2=%d\n", fdt2);

    fd_new11 = fcntl(fifo_rd_fd, F_DUPFD_CLOEXEC, 0);
    fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
    printf("000fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

    printf("%s line %d\n", __FUNCTION__, __LINE__);
    //fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
    fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
   // fifo_wr_fd = open(fifo_render_name, O_WRONLY);
printf("%s line %d fifo_wr_fd=%d\n", __FUNCTION__, __LINE__, fifo_wr_fd);
    //unlink(fifo_retrieve_name);
    //printf("%s line %d\n", __FUNCTION__, __LINE__);
    //mkfifo(fifo_retrieve_name, 0777);
    //printf("%s line %d\n", __FUNCTION__, __LINE__);
   // fifo_rd_fd = open(fifo_retrieve_name, O_RDONLY|O_CREAT|O_NONBLOCK, S_IRWXG);
///printf("%s line %d fifo_rd_fd=%d\n", __FUNCTION__, __LINE__, fifo_rd_fd);
    while (1)
    {
        BufferItem item;
        status_t status = fakeCameraConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0), 0);
        if (status == NO_ERROR)
        {
            sp<GraphicBuffer> graphicBuffer;// = fakeCameraConsumer->mSlots[item.mSlot].mGraphicBuffer;
            fakeCameraConsumer->getGraphicBuffer(item.mSlot, graphicBuffer);
            
            uint32_t* dataOut;
            graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&dataOut));

            //error: item.mFrameNumber is uint64_t type
            //printf("slot=%d, frameNum=%d, the data out is %d, dataOut=0x%x\n", item.mSlot, item.mFrameNumber, *dataOut, dataOut);

            printf("slot=%d, frameNum=%llu, the data out is %d, dataOut=0x%x\n", item.mSlot, item.mFrameNumber, *dataOut, dataOut);
            //printf("slot=%d, frameNum=%d, the data out is %d, dataOut=0x%x\n", item.mSlot, (int)item.mFrameNumber, *dataOut, dataOut);

            //////////////////////////////////////////////

            //fd = open( "zieckey_fifo", O_WRONLY );
            //write(fifo_wr_fd, s, sizeof(s));

            int shared_fd = 0;
            int err = gralloc4::get_share_fd((buffer_handle_t)graphicBuffer->handle, &shared_fd);
            if (err != android::OK)
            {
                printf("gralloc4::get_share_fd failed, err=%d", err);
            }
            else
            {
                //ipc_fd_socket_send(ipc_sock, shared_fd);
                char data_ptr[8] = "1234567";
                int data_len = sizeof(data_ptr);
                int s = ipc_fd_socket_send(ipc_sock, shared_fd, data_ptr, data_len);
                if (s <= 0)
                {
                    printf("ipc_fd_socket_send failed, err=%d", s);
                }

                if (fifo_wr_fd <= 0)
                {
                    //fifo_wr_fd = open(fifo_render_name, O_WRONLY|O_NONBLOCK);
                    // fifo_wr_fd = open(fifo_render_name, O_WRONLY);
                    //printf("%s line %d fifo_wr_fd=%d\n", __FUNCTION__, __LINE__, fifo_wr_fd);
                }

                if (fifo_wr_fd > 0)
                {

                    // printf("shared_fd=%d\n", shared_fd);
                    // int fd_new = fcntl(shared_fd, F_DUPFD_CLOEXEC, 0);
                    // printf("fd_new1=%d\n", fd_new);
                    // int fd_new11 = fcntl(shared_fd, F_DUPFD_CLOEXEC, 0);
                    // int fd_new2 = fcntl(fd_new, F_DUPFD_CLOEXEC, 0);
                    // printf("fd_new2=%d, fd_new11=%d\n", fd_new2, fd_new11);

                    // //write(fifo_wr_fd, &shared_fd, sizeof(int));
                    // write(fifo_wr_fd, &fd_new, sizeof(int));
                    // int retri_fd = 0;
                    // usleep(80000);
                    // read(fifo_rd_fd, &retri_fd, sizeof(int));

                    // if (shared_fd != retri_fd)
                    // {
                    //     printf("error ############ shared_fd=(%d) != retri_fd(%d)\n", shared_fd, retri_fd);
                    // }

                    //test fd rga
                    #if 0
                        int src_width = 1920;
                        int src_height = 1080;
                        static unsigned long src_fd = 0;
                        static unsigned long dst_fd = 0;
                        int dst_width = 1920;
                        int dst_height = 1080;
                        int zoom_val = 100;
                        bool mirror = false;
                        bool isNeedCrop = true;
                        bool isDstNV21 = false;
                        bool is16Align = true;
                        bool isYuyvFormat = false;

                        if (src_fd == 0) src_fd = shared_fd;

                            //                         camera2::RgaCropScale::rga_nv12_scale_crop(
                            // tempFrameWidth, tempFrameHeight, gb_shared_fd, handle_fd,
                            // halBuf.width, halBuf.height, 100, false, true,
                            // (halBuf.format == PixelFormat::YCRCB_420_SP), is16Align,
                            // false);

                        if (src_fd > 0 && dst_fd > 0)
                        {
                            int ret44 = rga_nv12_scale_crop(
                                src_width, src_height,
                                src_fd, dst_fd,
                                dst_width, dst_height,
                                zoom_val, mirror, isNeedCrop,
                                isDstNV21, is16Align, isYuyvFormat);
                            if (ret44 != 0)
                            {
                                printf("rga_nv12_scale_crop failed, ret=%d\n", ret44);
                            }
                            else
                            {
                                printf("rga_nv12_scale_crop ok, ret=%d\n", ret44);
                            }
                        }

                        dst_fd = shared_fd;

                    #endif
                }
            }

            /////////////////////////////////////////////

            if (fp)
            {
                fwrite(dataOut, 1, frame_size, fp);
                //fflush(fp);
            }

            graphicBuffer->unlock();

            fakeCameraConsumer->releaseBuffer(item.mSlot);
        }

        usleep(1000000);
    }

printf("%s line %d  ooo\n", __FUNCTION__, __LINE__);

    if (fp)
        fclose(fp);
}

extern const char *kDefaultDriver;
void bq_producer_client_thread();



int main(int argc, char** argv)
{
printf("%s line %d\n", __FUNCTION__, __LINE__);
    ALOGI("kDefaultDriver=%s", kDefaultDriver);

    #if 0
    int fdt1 = open("/data/local/tmp/test_server", O_RDONLY);
    printf("8800fdt1=%d\n", fdt1);
    int fdt2 = fcntl(fdt1, F_DUPFD_CLOEXEC, 0);
    printf("8800fdt2=%d\n", fdt2);

    const char fifo_render_name[32] = "/data/fifo_render";
    const char fifo_retrieve_name[32] = "/data/fifo_retrieve";
    static int fifo_wr_fd = 0;
    static int fifo_rd_fd = 0;
    int gb_shared_fd = 0;

    //int ret = access(fifo_render_name, F_OK);
    if (::access(fifo_render_name, F_OK) == 0 && ::access(fifo_retrieve_name, F_OK) == 0)
    {
        if (fifo_rd_fd <= 0)
            fifo_rd_fd = ::open(fifo_render_name, O_RDONLY|O_NONBLOCK);
        if (fifo_wr_fd <= 0)
            fifo_wr_fd = ::open(fifo_retrieve_name, O_WRONLY|O_NONBLOCK);


        while (1)
        {
            gb_shared_fd = 0;
            if (fifo_rd_fd > 0)
                ::read(fifo_rd_fd, &gb_shared_fd, sizeof(int));

            if (gb_shared_fd > 0)
            {
                int new_gb_shared_fd = fcntl(gb_shared_fd, F_DUPFD_CLOEXEC, 0);

                printf("gb_shared_fd=%d, new_gb_shared_fd=%d.\n", gb_shared_fd, new_gb_shared_fd);
                

                                   //test fd rga
                    #if 1
                        int src_width = 1920;
                        int src_height = 1080;
                        static unsigned long src_fd = 0;
                        static unsigned long dst_fd = 0;
                        int dst_width = 1920;
                        int dst_height = 1080;
                        int zoom_val = 100;
                        bool mirror = false;
                        bool isNeedCrop = true;
                        bool isDstNV21 = false;
                        bool is16Align = true;
                        bool isYuyvFormat = false;

                        if (src_fd == 0) src_fd = new_gb_shared_fd;

                            //                         camera2::RgaCropScale::rga_nv12_scale_crop(
                            // tempFrameWidth, tempFrameHeight, gb_shared_fd, handle_fd,
                            // halBuf.width, halBuf.height, 100, false, true,
                            // (halBuf.format == PixelFormat::YCRCB_420_SP), is16Align,
                            // false);

                        if (src_fd > 0 && dst_fd > 0)
                        {
                            int ret44 = rga_nv12_scale_crop(
                                src_width, src_height,
                                src_fd, dst_fd,
                                dst_width, dst_height,
                                zoom_val, mirror, isNeedCrop,
                                isDstNV21, is16Align, isYuyvFormat);
                            if (ret44 != 0)
                            {
                                printf("888 rga_nv12_scale_crop failed, ret=%d\n", ret44);
                            }
                            else
                            {
                                printf("8888rga_nv12_scale_crop ok, ret=%d\n", ret44);
                            }
                        }

                        dst_fd = new_gb_shared_fd;

                    #endif

            }

            printf("8800gb_shared_fd=%d\n", gb_shared_fd);
            usleep(500000);
            
        }
    }

    return 0;
    #endif

    ipc_sock = ipc_fd_socket_init();

    ALOGI("server 00 binder drivername: %s", ProcessState::self()->getDriverName().c_str());

    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);

    fakeCameraConsumer = new FakeCameraConsumer(consumer, false);

    sp<IServiceManager> serviceManager = defaultServiceManager();
    serviceManager->addService(String16("MyProducer"), IInterface::asBinder(producer));
    serviceManager->addService(String16("MyConsumer"), IInterface::asBinder(consumer));

    ProcessState::self()->startThreadPool();

    ALOGI("server binder drivername: %s", ProcessState::self()->getDriverName().c_str());
printf("%s line %d\n", __FUNCTION__, __LINE__);
    std::thread consumer_th(consumer_process_thread);
printf("%s line %d\n", __FUNCTION__, __LINE__);
    std::thread producer_th(bq_producer_client_thread);
printf("%s line %d\n", __FUNCTION__, __LINE__);
    IPCThreadState::self()->joinThreadPool();
printf("%s line %d\n", __FUNCTION__, __LINE__);
    return 0;
}

#else

struct DummyConsumer : public BnConsumerListener {
    void onDisconnect() override
    {
        printf("producer is disconnected.\n");
    }

    void onFrameAvailable(const BufferItem& item) override 
    {
        printf("onFrameAvailable: framenumber=%llu.\n", item.mFrameNumber);
    }

    void onBuffersReleased() override 
    {

    }

    void onSidebandStreamChanged() override 
    {

    }

};

// void consumer_process_thread(void *arg)
// {
//     sp<IGraphicBufferConsumer> consumer = ;
// }

sp<IGraphicBufferConsumer> consumer;

void consumer_process_thread()
{
    /****************** Consumer ***********************/
    while (1)
    {
        //printf("#####################\n");

        BufferItem item;
        status_t status = consumer->acquireBuffer(&item, static_cast<nsecs_t>(0));
        if (status == NO_ERROR)
        {
            if (item.mGraphicBuffer != NULL)
            {
                //printf("##################1##\n");
                //if (item.mGraphicBuffer == NULL)
                //    printf("##################1#mGraphicBuffer=NULL#\n");
                //printf("##################1#item=0x%x#\n",item);
                //printf("##################1#item.mGraphicBuffer=0x%x#\n", reinterpret_cast<uint32_t *>(item.mGraphicBuffer));
                //printf("##################1##\n");
                uint32_t* dataOut;
                item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
                                reinterpret_cast<void**>(&dataOut));
                printf("the data out is %d\n", *dataOut);
                item.mGraphicBuffer->unlock();
                //printf("###############2######\n");                   
            }
            else
            {
                printf("item.mAcquireCalled=%d, slot=%d, item.mFrameNumber=%d\n", item.mAcquireCalled, item.mSlot, item.mFrameNumber);
            }

            printf("server get slot=%d, item.mFrameNumber=%d\n", item.mSlot, item.mFrameNumber);
        }

        consumer->releaseBuffer(item.mSlot, item.mFrameNumber, EGL_NO_DISPLAY,
            EGL_NO_SYNC_KHR, Fence::NO_FENCE);


        usleep(1000000);
    }
}

int main(int argc, char** argv)
{
    sp<IGraphicBufferProducer> producer;
    //sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);

    consumer->consumerConnect(new DummyConsumer, false);

    sp<IServiceManager> serviceManager = defaultServiceManager();
    serviceManager->addService(String16("MyProducer"), IInterface::asBinder(producer));
    serviceManager->addService(String16("MyConsumer"), IInterface::asBinder(consumer));

    ProcessState::self()->startThreadPool();


    //std::thread consumer_th(consumer_process_thread, (void *)consumer);
    std::thread consumer_th(consumer_process_thread);

    IPCThreadState::self()->joinThreadPool();

    return 0;
}

#endif